package com.echo.code.thread.lock.impl;

import com.echo.code.thread.lock.Lock;
import com.echo.code.thread.lock.helper.impl.ReadWriteLockHelperImpl;
import java.util.concurrent.TimeoutException;
import java.util.logging.Logger;

/**
 * WriteLock Created by baiyap on 2018/9/24.
 */
public class WriteLock implements Lock {

  private static final Logger LOGGER = Logger.getLogger(WriteLock.class.getName());

  private final ReadWriteLockHelperImpl helper;

  public WriteLock(ReadWriteLockHelperImpl helper) {
    this.helper = helper;
  }

  @Override
  public void lock() throws InterruptedException {
    synchronized (helper.getMutex()) {
      helper.incrementWaitingWriters();
      while (helper.getWritingWriters() > 0 || helper.getReadingReaders() > 0) {
        LOGGER.info(getCurrentThreadName() + "can not get the write lock and suspend...");
        try {
          helper.getMutex().wait();
        } catch (InterruptedException e) {
          helper.decrementWaitingWriters();
          throw e;
        }
      }
      LOGGER.info(getCurrentThreadName() + " obtain the write lock.");
      helper.decrementWaitingWriters();
      helper.incrementWritingWriters();
    }
  }

  @Override
  public void unlock() {
    synchronized (helper.getMutex()) {
      LOGGER.info(getCurrentThreadName() + "release the write lock.");
      helper.decrementWritingWriters();
      helper.changePreferWriter(Boolean.FALSE);
      helper.getMutex().notifyAll();
    }
  }

  @Override
  public void lock(long mills) throws InterruptedException, TimeoutException {
    // TODO
    return;
  }
}
